package com.ysd.lis.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.yulichang.toolkit.JoinWrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.ysd.common.Result;
import com.ysd.lis.entity.*;
import com.ysd.lis.mapper.WkTrainingKnowledgeMapper;
import com.ysd.lis.mapper.WkTrainingPlanMapper;
import com.ysd.lis.mapper.WkTrainingUserMapper;
import com.ysd.lis.service.WkTrainingKnowledgeService;
import com.ysd.lis.service.WkTrainingPlanService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ysd.lis.service.WkTrainingUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * <p>
 * 培训计划表 服务实现类
 * </p>
 *
 * @author LiuQi
 * @since 2024-03-20
 */
@Service
public class WkTrainingPlanServiceImpl extends ServiceImpl<WkTrainingPlanMapper, WkTrainingPlan> implements WkTrainingPlanService {

    @Autowired
    WkTrainingPlanMapper wkTrainingPlanMapper;

    @Autowired
    WkTrainingUserService wkTrainingUserService;

    @Autowired
    WkTrainingUserMapper wkTrainingUserMapper;

    @Autowired
    WkTrainingKnowledgeService wkTrainingKnowledgeService;

    @Autowired
    WkTrainingKnowledgeMapper wkTrainingKnowledgeMapper;

    /**
     * 获取培训列表
     *
     * @param keyWord
     * @return
     */
    @Override
    public Result getTrainingPlanList(String keyWord, Integer status) {
        MPJLambdaWrapper<WkTrainingPlan> lambdaQueryWrapper = JoinWrappers.lambda(WkTrainingPlan.class)
                .selectAll(WkTrainingPlan.class)
                .selectCollection(WkTrainingUser.class, WkTrainingPlan::getSysUserList, map -> map
                        .id(WkTrainingUser::getUserId, SysUser::getId)
                        .result(WkTrainingUser::getUserName, SysUser::getRealname)
                        .result(WkTrainingUser::getIsSign, SysUser::getDiffer))
                .selectCollection(WkTrainingKnowledge.class, WkTrainingPlan::getKnowledgeIds, map -> map
                        .result(WkTrainingKnowledge::getKnowledgeId))
                .leftJoin(WkTrainingUser.class, WkTrainingUser::getTrainingId, WkTrainingPlan::getId)
                .leftJoin(WkTrainingKnowledge.class, WkTrainingKnowledge::getTrainingId, WkTrainingPlan::getId)
                .eq(WkTrainingPlan::getDelFlag, 0)
                .eq(ObjectUtil.isNotNull(status), WkTrainingPlan::getStatus, status)
                .and(StrUtil.isNotEmpty(keyWord), wrapper -> wrapper.like(WkTrainingPlan::getTrainingCode, keyWord).or().like(WkTrainingPlan::getTrainingName, keyWord))
                .orderByAsc(WkTrainingPlan::getSeq);
        List<WkTrainingPlan> wkTrainingPlans = wkTrainingPlanMapper.selectJoinList(WkTrainingPlan.class, lambdaQueryWrapper);
        List<WkTrainingPlan> resultWkTrainingPlans = wkTrainingPlans.stream().map(item -> {
            if (CollUtil.isNotEmpty(item.getSysUserList()) && !item.getSysUserList().isEmpty()) {
                Map<Integer, List<SysUser>> signMap = item.getSysUserList().stream().collect(Collectors.groupingBy(SysUser::getDiffer));
                item.setSignNo(signMap.containsKey(1) ? signMap.get(1).size() : 0);
                item.setNotSignNo(signMap.containsKey(0) ? signMap.get(0).size() : 0);
                item.setRefuseSignNo(signMap.containsKey(2) ? signMap.get(2).size() : 0);
                int i = signMap.containsKey(1) ? signMap.get(1).size() : 0;
                item.setParticipationRate(Math.round(((double) i / item.getSysUserList().size()) * 100) / 100.0);
            } else {
                item.setParticipationRate(0.0);
            }
            return item;
        }).collect(Collectors.toList());
        return Result.succ(1, "查询成功！", resultWkTrainingPlans);
    }

    /**
     * 根据id联表查询培训信息
     *
     * @param id
     * @return
     */
    @Override
    public Result getTrainingInfo(String id, String userId) {
        MPJLambdaWrapper<WkTrainingPlan> lambdaQueryWrapper = JoinWrappers.lambda(WkTrainingPlan.class)
                .selectAll(WkTrainingPlan.class)
                .selectCollection(WkTrainingUser.class, WkTrainingPlan::getSysUserList, map -> map
                        .id(WkTrainingUser::getUserId, SysUser::getId)
                        .result(WkTrainingUser::getUserName, SysUser::getRealname)
                        .result(WkTrainingUser::getIsSign, SysUser::getDiffer))
                .selectCollection(WkTrainingKnowledge.class, WkTrainingPlan::getKnowledgeList, map -> map
                        .id(WkTrainingKnowledge::getKnowledgeId, WkKnowledgeContent::getId)
                        .result(WkTrainingKnowledge::getKnowledgeTitle, WkKnowledgeContent::getTitle)
                        .collection(WkContentViewTime.class, WkKnowledgeContent::getDurationList))
                .leftJoin(WkTrainingUser.class, WkTrainingUser::getTrainingId, WkTrainingPlan::getId)
                .leftJoin(WkTrainingKnowledge.class, WkTrainingKnowledge::getTrainingId, WkTrainingPlan::getId)
                .leftJoin(WkContentViewTime.class, WkContentViewTime::getKnowledgeContentId, WkTrainingKnowledge::getKnowledgeId, on -> on.eq(WkContentViewTime::getUserId, userId))
                .eq(WkTrainingPlan::getId, id);
        WkTrainingPlan wkTrainingPlan = wkTrainingPlanMapper.selectJoinOne(WkTrainingPlan.class, lambdaQueryWrapper);
        return Result.succ(1, "查询成功！", wkTrainingPlan);
    }

    /**
     * 根据用户id查询培训列表
     *
     * @param userId
     * @return
     */
    @Override
    public Result getTrainingListByUserId(String userId) {
        MPJLambdaWrapper<WkTrainingPlan> lambdaQueryWrapper = JoinWrappers.lambda(WkTrainingPlan.class)
                .selectAll(WkTrainingPlan.class)
                .leftJoin(WkTrainingUser.class, WkTrainingUser::getTrainingId, WkTrainingPlan::getId)
                .eq(WkTrainingPlan::getDelFlag, 0)
                .eq(WkTrainingPlan::getStatus, 1)
                .eq(StrUtil.isNotEmpty(userId), WkTrainingUser::getUserId, userId);
        List<WkTrainingPlan> wkTrainingPlans = wkTrainingPlanMapper.selectJoinList(WkTrainingPlan.class, lambdaQueryWrapper);
        return Result.succ(1, "查询成功！", wkTrainingPlans);
    }

    /**
     * 根据知识库内容id查询培训列表
     *
     * @param knowledgeId
     * @return
     */
    public Result getTrainingListByKnowledgeId(String knowledgeId) {
        MPJLambdaWrapper<WkTrainingPlan> lambdaQueryWrapper = JoinWrappers.lambda(WkTrainingPlan.class)
                .selectAll(WkTrainingPlan.class)
                .selectCollection(WkTrainingUser.class, WkTrainingPlan::getSysUserList, map -> map
                        .id(WkTrainingUser::getUserId, SysUser::getId)
                        .result(WkTrainingUser::getUserName, SysUser::getRealname)
                        .result(WkTrainingUser::getIsSign, SysUser::getDiffer))
                .leftJoin(WkTrainingUser.class, WkTrainingUser::getTrainingId, WkTrainingPlan::getId)
                .leftJoin(WkTrainingKnowledge.class, WkTrainingKnowledge::getTrainingId, WkTrainingPlan::getId)
                .eq(WkTrainingPlan::getDelFlag, 0)
                .eq(WkTrainingPlan::getStatus, 1)
                .eq(StrUtil.isNotEmpty(knowledgeId), WkTrainingKnowledge::getKnowledgeId, knowledgeId);
        List<WkTrainingPlan> wkTrainingPlans = wkTrainingPlanMapper.selectJoinList(WkTrainingPlan.class, lambdaQueryWrapper);
        return Result.succ(1, "查询成功！", wkTrainingPlans);
    }


    /**
     * 插入计划表和培训人员表
     *
     * @param wkTrainingPlan
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result addTrainingPlan(WkTrainingPlan wkTrainingPlan) {
        boolean save = this.save(wkTrainingPlan);
        save = save && saveBatchWkTrainingUser(wkTrainingPlan, false);
        save = save && saveBatchWkTrainingKnowledge(wkTrainingPlan, false);
        if (save) {
            return Result.succ(1, "添加成功！", save);
        } else {
            return Result.fail("添加失败！");
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result updateTrainingPlan(WkTrainingPlan wkTrainingPlan) {
        boolean save = this.updateById(wkTrainingPlan);
        save = save && saveBatchWkTrainingUser(wkTrainingPlan, true);
        save = save && saveBatchWkTrainingKnowledge(wkTrainingPlan, true);
        if (save) {
            return Result.succ(1, "添加成功！", save);
        } else {
            return Result.fail("添加失败！");
        }
    }

    @Override
    public Result deleteTrainingPlanByIds(List<String> ids) {
        boolean delete = this.removeByIds(ids);
        if (delete) {
            return Result.succ(1, "删除成功！", delete);
        } else {
            return Result.fail("删除失败！");
        }
    }

    /**
     * 先清空，再插入
     *
     * @param wkTrainingPlan
     * @param isClear
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean saveBatchWkTrainingUser(WkTrainingPlan wkTrainingPlan, boolean isClear) {
        if (CollUtil.isNotEmpty(wkTrainingPlan.getSysUserList()) && !wkTrainingPlan.getSysUserList().isEmpty()) {
            if (isClear) {
                LambdaQueryWrapper<WkTrainingUser> lambdaQueryWrapper = new LambdaQueryWrapper<>();
                lambdaQueryWrapper.eq(WkTrainingUser::getTrainingId, wkTrainingPlan.getId());
                wkTrainingUserMapper.delete(lambdaQueryWrapper);
            }
            final AtomicInteger index = new AtomicInteger(1);
            List<WkTrainingUser> collect = wkTrainingPlan.getSysUserList().stream().map(item -> {
                WkTrainingUser wkTrainingUser = new WkTrainingUser();
                wkTrainingUser.setUserId(item.getId());
                wkTrainingUser.setUserName(item.getRealname());
                wkTrainingUser.setIsSign(0);
                wkTrainingUser.setSeq(index.getAndAdd(1));
                wkTrainingUser.setTrainingId(wkTrainingPlan.getId());
                return wkTrainingUser;
            }).collect(Collectors.toList());
            return wkTrainingUserService.saveBatch(collect);
        }
        return false;
    }

    /**
     * 先清空，再插入
     *
     * @param wkTrainingPlan
     * @param isClear
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean saveBatchWkTrainingKnowledge(WkTrainingPlan wkTrainingPlan, boolean isClear) {
        if (CollUtil.isNotEmpty(wkTrainingPlan.getKnowledgeIds()) && !wkTrainingPlan.getKnowledgeIds().isEmpty()) {
            if (isClear) {
                LambdaQueryWrapper<WkTrainingKnowledge> lambdaQueryWrapper = new LambdaQueryWrapper<>();
                lambdaQueryWrapper.eq(WkTrainingKnowledge::getTrainingId, wkTrainingPlan.getId());
                wkTrainingKnowledgeMapper.delete(lambdaQueryWrapper);
            }
            final AtomicInteger index = new AtomicInteger(1);
            List<WkTrainingKnowledge> collect = wkTrainingPlan.getKnowledgeList().stream().map(item -> {
                WkTrainingKnowledge wkTrainingKnowledge = new WkTrainingKnowledge();
                wkTrainingKnowledge.setKnowledgeId(item.getId());
                wkTrainingKnowledge.setKnowledgeTitle(item.getTitle());
                wkTrainingKnowledge.setSeq(index.getAndAdd(1));
                wkTrainingKnowledge.setTrainingId(wkTrainingPlan.getId());
                return wkTrainingKnowledge;
            }).collect(Collectors.toList());
            return wkTrainingKnowledgeService.saveBatch(collect);
        }
        return false;
    }

}
